-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Syntect highlighting experiment #73
base: main
Are you sure you want to change the base?
Conversation
dc8231a
to
54cbb44
Compare
54cbb44
to
9e63cbe
Compare
Looking amazing so far, thanks for opening the PR! Can't wait for this to be ready for review, if you stick with it. |
8fbeb4f
to
e02e0e8
Compare
e02e0e8
to
7395f56
Compare
c53520d
to
a7350fe
Compare
a7350fe
to
17068a7
Compare
The code is starting to look a little better, though there's still a few things to do. I made the syntax highlighting optional (still need to fix the config, though). When disabled it uses the current look. Also, I tried to see how it looks when only the selected hunk is highlighted: I personally like it, what do you think? I could also see if I can make this optional. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few notes/questions! Don't mean to step on your toes too much since I know this is a draft PR. Really appreciate the work you're doing here.
Also, I tried to see how it looks when only the selected hunk is highlighted:
I'm a big fan of the look and feel of this. I do think this functionality should be configurable, but also I think it should be the default behaviour for now (time will tell).
I wonder if the whole file diff should be highlighted when the file is selected (rather than a hunk under the file) as well.
@@ -64,6 +65,8 @@ impl Default for Options { | |||
lookahead_lines: 5, | |||
truncate_lines: true, | |||
ws_error_highlight: WsErrorHighlight::default(), | |||
// TODO: decide on default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, I think the default syntax highlighting theme should come from the terminal's theme (just as the default gex colour theme does). This should make life a bit easier for users as some colour coherency is ensured out of the box.
I am not sure of the feasibility of this since Syntect only accepts colors as RGBA. This StackOverflow answer suggests that in at least xterm you can query the current terminal colors, but I haven't investigated how cross-platform this approach is, and I don't think it's supported in Crossterm.
This will be a decent amount of work to look into and is definitely not blocking for this PR - but my gut feeling is that as long as this isn't possible, then syntax highlighting should be disabled by default. Let me know your thoughts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is a viable solution since, as you mentioned there doesn't seem to be a reliable way to get the terminal's colors.
I think a "better" way could be creating a custom syntect theme and then map the Style
s back to the 16 color ANSI sequenses and display them using crossterm. But I don't think I'll explore that option in this PR for now.
Either way, I agree that gex should be usable out-of-the-box even on terminals that don't support true-color / 24 bit colors. So yeah, the highlighting should be disabled by default.
|
||
// workaround: remove trailing line break | ||
buf.pop(); | ||
buf.push_str("\x1b[0m"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't investigated but my suspicion is that resetting attributes this way will break things if the user has a custom background color set. The render::terminal
module provides a ResetAttributes
that should do what you want (if it doesn't then that's probably a bug with ResetAttributes
).
buf.pop(); | ||
|
||
// according to docs of `as_24_bit_terminal_escaped` | ||
buf.push_str("\x1b[0m"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See prior comment
syntax: &SyntaxReference, | ||
) -> String { | ||
// TODO: move somewhere else? | ||
let marker_added = as_24_bit_terminal_escaped(&[(MARKER_ADDED_STYLE, MARKER_ADDED)], true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is unclear to me why we use as_24_bit_terminal_escaped
instead of the crossterm Command API
|
||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
pub enum DiffLineType { | ||
Unchanged, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bikeshed (not important): how do we feel about changing this variant to Context
to bring it inline with git's documentation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I'm not familiar with the exact naming in git so I just chose something. I'll also use "deleted" instead of "removed" since I think I saw these used in other parts of gex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't pay it much thought before but come to think of it, git actually uses "old" and "new" where in gex we use "deletion" and "addition", so it's already inconsistent. To be honest old and new don't sound as obvious to me personally, could just be my bias.
Anyway, this is far from an important point about the code so I will stop fixating on it 😅
' ' => Ok(Self::Unchanged), | ||
'+' => Ok(Self::Added), | ||
'-' => Ok(Self::Removed), | ||
c => Err(anyhow!("'{c}' is not a valid diff type character.")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of an added trailing newline this will cause a bug (see #62)
Thanks for the first review, appreciate it! I'll probably take my time with this PR. One problem I didn't notice until now is that highlighting each hunk in isolation is wrong, since it doesn't always produce valid syntax. |
Absolutely take your time. Thanks again for taking a look at this!
Seems good to me! |
Adds optional syntax highlighting based on syntect to hunk diffs.
screenshots
with background color:
Remaining things to fix/consider (not all changes are pushed to the branch, yet):
Use separate highlighter instance for added and removed lines to keep the syntax intact.Add inline highlighting for single line changes.@@...@@
into the highlighter.Try highlighting the background to the whole width of the terminal?Use syntax theme background color?